perm filename A03[106,RWF] blob
sn#749338 filedate 1984-04-03 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00005 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 Strings
C00010 00003 Definitions
C00017 00004 Command:
C00020 00005 A pure function is very easy to test separately from the rest of the program.
C00024 ENDMK
C⊗;
Strings
"What do you get when you cross a Neptunian with a Uranian? Somebody who
steals space ships, but can't drive them."
What happens when you cross characters and arrays? Well, on Uranus they tried
to do it by letting arrays be characters. When they found that to handle
2 by 2 arrays of real numbers as characters they would need more keys on each
keyboard than there are electrons in the universe, they quadrupled the tentacle
tax to pay for it. The dodecapods rebelled, the government fell, and computers
were outlawed. We do it differently.
Our written languages are based on sequences of characters: words, sentences,
paragraphs, books, titles, part numbers, license plates, mathematical formulas,
even computer programs. In Pascal, values like these are kept in arrays of
characters. Such arrays are called strings.
Things we might want a computer to do with strings:
(1) Matching. Let's say that somewhere in a large manuscript I remember
using the phrase "begging the question". I've learned that I misused the
term, so I want to find that place. Probably to find "begging" will suffice.
(2) Substitution. I have developed a program using shorthand names for the
variables. Now I wnat to change GW to GROSSWAGES throughout the program.
(3) Alphabetization. I have an array of strings, each containing the name,
address, and telephone number of one employee. I want to arrange them in
alphabetical order by name, to print a company directory.
(4) Formatting. I want to rearrange my manuscript so that paragraphs are
separated by blank lines, and lines are stretched by insertion of spaces to
give straight margins on left and right. I also want to center the chapter
headings. Or I want to consistently space and indent a Pascal program.
(5) Interpretation. I want my program to read phrases like "three thousand
two hundred eighty" on a check, or "gale force winds" on a meteorological
report and translate them into numerical equivalents.
(6) Translation. I want to provide a word-by-word translation from Spanish
to English.
_String Types_
A string type is a type name that has been defined to be
PACKED ARRAY [1..N] OF CHAR
for some integer constant N. In this text, we will include the value of
N in the names we use for string types; we might define
TYPE STRING8O = PACKED ARRAY[1..80] OF CHAR;
Such types can be used as types of program variables
VAR LINE1, LINE2: STRING80;
or of subprogram parameters
PROCEDURE CENTER (INPUTLINE: STRING80; VAR OUTPUTLINE: STRING80);
They may not, unfortunately, be used as types of function results in Standard
Pascal.
We can do with strings all the operations implicit in an array of
characters. To find if a word ends in a vowel we might use the program
fragment:
...
...
VAR WORD: STRING20;
C: CHAR;
...
I:=1;
WHILE WORD[I+1] <> ` ' DO I:=I+1;
(*NOW WORD[I+1] IS BLANK*)
C:=WORD[I];
IF (C=`A') OR ... OR (C=`U') THEN S1 ELSE S2
Additionally, Pascal includes some operations automatically defined for string
types. If X and Y are of the _same_ string type, they can be tested for
equality and for alphabetical order:
VAR X,Y: STRING20;
...
...
IF X=Y THEN WRITE ('SAME WORD')
ELSE IF X<Y THEN WRITE ('X COMES BEFORE Y')
ELSE WRITE ('Y COMES BEFORE X')
The tests of alphabetical order are based on the ordering of the
characters, so the results are probably not what you want if the strings
mix capital with lower case letters. In the ASCII code, for example,
'zebra___' comes before 'AARDVARK', because a lower case letter z comes
before an upper case letter A.
You can read to a string variable:
READ(WORD)
reads one line of an input text file, adds spaces on the right if necessary,
and assigns the resulting string to WORD. If the line is longer than WORD,
the command reads only enough to fill WORD.
The string constants belong to the string types of the same length; you can
assign
WORD:='ABCDEFGHIJKLMNOPQRST';
if WORD is of type STRING20.
You can print a string.
WRITELN(WORD) prints ABCD...RST
The list above contains all of the builtin operations in strings in Pascal.
Comparing it to the long list of functions, operators, and relations on
numbers, you can see that Pascal was designed more to work on numbers than
on strings. Many Pascal implementations, though, have extensions ("string
packages") to do more, and programmers can design their own procedures to
do common string manipulations. Here is one to capitalize letters in
string LINE1, putting the result in LINE2:
PROCEDURE CAPITALIZE(LINE1:STRING80;VAR LINE2: STRING80);
VAR I:INTEGER;
BEGIN
FOR I:=1 TO 80 DO
IF LINE1[I] IN [`a'..`z'] THEN
LINE2[I]:=CHR(LINE1[I] - ORD(`a') + ORD(`A')
ELSE LINE2[I]:=LINE1[I]
END;
Definitions
In describing a programming language, it is convenient to factor the definition
into syntax, semantics, and pragmatics. Syntax is the grammar of the language;
it defines which texts are in the language, and how each program is subdivided
into meaningful parts. Semantics defines a meaning for each syntactically correct
program, usually by saying what sequence of actions the program performs.
Pragmatics is concerned with usage and practicality. Pragmatic details of a
language include the cost in time or money of executing a program, the resources
(such as memory capacity) the computer must have, and the precision with which
calculation is done.
The syntactic definition of the part of Pascal already introduced follows
Program:
PROGRAM name (OUTPUT);
variable
declaration ;
BEGIN command ; END.
Name:
letter letter
digit
underline
Variable Declaration:
VARIABLE name , : INTEGER
REAL
Command:
WRITE ( operand , )
WRITELN
FOR variable := expr TO expr DO command
BEGIN command ; END
WRITE(I), where I is an integer-valued expression, prints the value of I,
preceded by enough blanks to make a total of 12 characters.
*************
WRITE(R), where R is a real-valued expression, prints the value of R....
WRITELN by itself adds a carriage return to the output file; subsequent printing
will be on a new line.
WRITE(A,B,C) and WRITELN(A,B,C) abbreviate
BEGIN BEGIN
WRITE(A); WRITE(A);
WRITE(B); WRITE(B);
WRITE(C); WRITE(C);
END WRITELN
END
The files created by WRITE and WRITELN should have no more than 132 characters
per line for printing, and no more than 80 per line for display.
Rule of Good Programming Practice: Check that your program, by using WRITELN,
prevents accumulation of oversized output lines.
Expressions include constants and variables. They also can be built up from smaller
expressions using standard operations and functions. If A and B are two
expressions, and a and b are their respective numerical values, the first column
in the following table lists expressions that can be built from A and B; the
second column gives the value of the built-up expression
Expression Value
A + B a + b
A - B a - b
A * B a x b
A / B a / b (an error if b = 0)
+A a
-A -a
A DIV B the integer part of a / b; a and b must be integers
(A) a
ABS(A) |a|
SQR (A) a
SIN (A) sine(a)
COS (A) cosine(a)
LN (A) log (a) (an error if a≤0)
EXP (A) e
SQRT (A) a (an error if a<0)
ARCTAN (A) tan(a) in the range -π/2, π/2
A pure function is very easy to test separately from the rest of the program.
If it works with numbers, we can try it with constant arguments C1,C2,...Cn
by incorporating the function definition in this program:
PROGRAM....(OUTPUT);
definition of function F;
BEGIN
WRITELN(C1,C2,...,Cn,F(C1,C2,...,Cn))
END.
The penultimate line can be repeated with as many different argument values as
needed, or one can iterate:
FOR I:= 1 to N DO
BEGIN
READ(X1,X2,...,XN);
WRITELN(X1,X2,...,XN,F(X1,X2,...,XN)
END
Such a program is called a driver; its only purpose is to test a pure function on
data for which the correct result is known.
Conversely, it is easy to test the main program without the correct definition of
the pure function, replacing the function's definition by some easy function.
If the main program is designed to form the sum F(1)+F(2)+...+F(100), and the
correct definition of F is difficult, we can test the summation and the printing
format by using the function F(X)=X, this way:
PROGRAM P(OUTPUT);
VAR
FUNCTION F(I:INTEGER:REAL;
BEGIN
F:=I
END;
BEGIN
SUM:=0.0
FOR J:= 1 TO 100 DO
SUM:= SUM + F(J);
WRITELN SUM:6:2
END.
If the program prints 5050.00, we know that the main program is in good shape.
We have tested it using a stub in place of the correct subprogram; a stub goes
through the same motions as the absent subprogram, without necessarily giving
correct answers.
If the test of the master program requires that the subprogram give correct
answers, we can still test with a stub, but the stub now asks the user for help.
The declaration of the stub looks like:
FUNCTION F(X,Y:REAL):REAL;
BEGIN
WRITELN(TTY,'WHAT IS F IF X AND Y ARE',X,Y);
READ(TTY,X,Y)
(* FOR A MORE RELIABLE TERMINAL INPUT *)
(* SEE SECTION ON FILES *)
END
Every part of a program under development can be tested separately, by using a
driver to substitute for its master program, and stubs to substitute for its
subprograms. This technique allows a team to subdivide a programming project
in such a way that no bottlenecks impede the testing.
Reference: Aron, The Programs Development Process.